package cn.dxs.adt.service;

import android.accessibilityservice.AccessibilityService;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Build;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;

import java.util.List;

import cn.dxs.adt.bean.WindowInfo;
import cn.dxs.adt.receiver.MAccessibilityServiceReceiver;
import cn.dxs.adt.utils.AsUtil;
import cn.dxs.adt.utils.L;
import cn.dxs.adt.accessibilitytool.MainFunctions;
import cn.dxs.adt.utils.NotificationUtil;

/**
 * 辅助服务
 */
public class WindowChangeDetectingService extends AccessibilityService {

    private static final String TAG = WindowChangeDetectingService.class.getSimpleName();

    // 辅助服务名称（包名+"/"+完整类名）
    public static final String SERVICE_NAME = "cn.dxs.adt/cn.dxs.adt.service.WindowChangeDetectingService";
    public static AccessibilityServiceListener listener;
    public static final int NOTIFICATION_ID = 0x1000;// 通知栏ID
    private MAccessibilityServiceReceiver mReceiver;// 广播接收器
    private NotificationManager mNotificationManager;// 通知栏管理器

    public static MainFunctions mainFunctions;

    public interface AccessibilityServiceListener {
        /**
         * 窗口改变监听回调
         *
         * @param packageName  包名
         * @param activityName activity名
         */
        void windowChange(String packageName, String activityName);
    }

    public static void setListener(AccessibilityServiceListener l) {
        L.d(TAG, "setCallback");
        listener = l;
    }


    private ActivityInfo tryGetActivity(ComponentName componentName) {
        try {
            return getPackageManager().getActivityInfo(componentName, 0);
        } catch (PackageManager.NameNotFoundException unused) {
            return null;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        L.d(TAG, "onCreate");
    }

    /**
     * 服务连接完成
     */
    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        L.d(TAG, "onServiceConnected");
        mainFunctions = new MainFunctions(this);
        mainFunctions.onServiceConnected();
        // 启动浮动窗口服务
        startService(new Intent(this, FloatingViewService.class));
        // 添加通知栏消息（将服务提升到前台）
        addNotification();

        // 注册广播接收器
        mReceiver = new MAccessibilityServiceReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(MAccessibilityServiceReceiver.SWITCH_ACTION);
        intentFilter.addAction(MAccessibilityServiceReceiver.CLOSE_ACTION);
        registerReceiver(mReceiver, intentFilter);

        // 代码配置参数
//        AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo();
//        accessibilityServiceInfo.eventTypes = 32;
//        accessibilityServiceInfo.feedbackType = 16;
//        accessibilityServiceInfo.flags = 2;
//        setServiceInfo(accessibilityServiceInfo);
    }

    /**
     * 添加通知
     */
    private void addNotification() {
        // 获取通知管理器
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        // Android O以上需要配置通知渠道
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(NotificationUtil.CHANNEL_ID, NotificationUtil.CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
            mNotificationManager.createNotificationChannel(channel);
        }
        // 获取Notification实例
        Notification notification = NotificationUtil.getNotificationByVersion(this);
        // 将辅助服务设置为前台服务
        startForeground(NOTIFICATION_ID, notification);
        // 显示Notification
        if (mNotificationManager != null) {
            mNotificationManager.notify(NOTIFICATION_ID, notification);
        }
    }

    /**
     * 接收辅助服务事件
     */
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
//        getEventType()	事件类型
//        getSource()	获取事件源对应的结点信息
//        getClassName()	获取事件源对应类的类型,比如点击事件是有某个Button产生的,那么此时获取的就是Button的完整类名
//        getText()	获取事件源的文本信息,比如事件是有TextView发出的,此时获取的就是TextView的text属性.如果该事件源是树结构,那么此时获取的是这个树上所有具有text属性的值的集合
//        isEnabled()	事件源(对应的界面控件)是否处在可用状态
//        getItemCount() 如果事件源是树结构,将返回该树根节点下子节点的数量
        if (event == null) {
            return;
        }
        L.d(TAG, "onAccessibilityEvent-event.getEventType()=" + event.getEventType());
        switch (event.getEventType()) {
            case AccessibilityEvent.TYPE_VIEW_CLICKED://1 界面点击
                break;
            case AccessibilityEvent.TYPE_VIEW_LONG_CLICKED://2
                break;
            case AccessibilityEvent.TYPE_VIEW_SELECTED://4
                break;
            case AccessibilityEvent.TYPE_VIEW_FOCUSED://8
                break;
            case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED://16 界面文字改动
                break;
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED://32 窗口状态改变
                if (event.getPackageName() != null && event.getClassName() != null) {
                    ComponentName componentName = new ComponentName(event.getPackageName().toString(), event.getClassName().toString());
                    if (tryGetActivity(componentName) != null) {
                        L.d(TAG, componentName.flattenToShortString());
                        WindowInfo.packageName = event.getPackageName().toString();
                        WindowInfo.className = componentName.flattenToShortString();
                        if (listener != null) {
                            listener.windowChange(event.getPackageName().toString(), componentName.flattenToShortString());
                        }
                    }
//                    if ("cn.dxs.adt.MainActivity".equals(event.getClassName().toString())) {
//                    }
//                    String className = event.getClassName().toString();
//                    if (className.equals("com.tencent.mm.ui.LauncherUI")) {
//                        getPacket();
//                    } else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI")) {
//                        openPacket();
//                    } else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI")) {
//                        close();
//                    }
                }
                break;
            case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED://64 通知状态改变
//                AsUtil.handleNotification(event);
                break;
            case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER://128
                break;
            case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT://256
                break;
            case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START://512
                break;
            case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END://1024
                break;
            case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED://2048 窗口内容改变
                break;
            case AccessibilityEvent.TYPE_VIEW_SCROLLED://4096
                break;
            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED://8192
                break;
            case AccessibilityEvent.TYPE_ANNOUNCEMENT://16384
                break;
            case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED://32768
                break;
            case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED://65536
                break;
            case AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY://131072
                break;
            case AccessibilityEvent.TYPE_GESTURE_DETECTION_START://262144
                break;
            case AccessibilityEvent.TYPE_GESTURE_DETECTION_END://524288
                break;
            case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START://1048576
                break;
            case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END://2097152
                break;
            case AccessibilityEvent.TYPE_WINDOWS_CHANGED://4194304
                break;
            case AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED://8388608
                break;
            case AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT://16777216
                break;
        }
        if (mainFunctions != null) {
            mainFunctions.onAccessibilityEvent(event);
        }
    }

    @Override
    protected boolean onKeyEvent(KeyEvent event) {
        if (mainFunctions != null) {
            return mainFunctions.onKeyEvent(event);
        }
        return super.onKeyEvent(event);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if (mainFunctions != null) {
            mainFunctions.onConfigurationChanged(newConfig);
        }
    }

    @Override
    public boolean onUnbind(Intent intent) {
        if (mainFunctions != null) {
            mainFunctions.onUnbind(intent);
            mainFunctions = null;
        }
        return super.onUnbind(intent);
    }

    /**
     * 服务中断
     */
    @Override
    public void onInterrupt() {

    }

    /**
     * 服务退出
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        L.d(TAG, "onDestroy");
        // 取消通知栏消息显示
        if (mNotificationManager != null) {
            mNotificationManager.cancel(NOTIFICATION_ID);
            mNotificationManager = null;
        }
        // 解注册广播接收器
        if (mReceiver != null) {
            unregisterReceiver(mReceiver);
            mReceiver = null;
        }
        // 停止前台服务
        stopForeground(true);
        stopService(new Intent(this, FloatingViewService.class));
    }

    /**
     * 关闭红包详情界面,实现自动返回聊天窗口
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
    private void close() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo != null) {
            //为了演示,直接查看了关闭按钮的id
            List<AccessibilityNodeInfo> infos = nodeInfo.findAccessibilityNodeInfosByViewId("@id/ez");
            nodeInfo.recycle();
            for (AccessibilityNodeInfo item : infos) {
                item.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
        }
    }

    /**
     * 模拟点击,拆开红包
     */
    private void openPacket() {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo != null) {
            //为了演示,直接查看了红包控件的id
            List<AccessibilityNodeInfo> list = null;
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2) {
                list = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mm:id/u5");
            }
            nodeInfo.recycle();
            for (AccessibilityNodeInfo item : list) {
                item.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
        }
    }

    /**
     * 模拟点击,打开抢红包界面
     */
    private void getPacket() {
        AccessibilityNodeInfo rootNode = getRootInActiveWindow();
        AccessibilityNodeInfo node = recycle(rootNode);

        node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        AccessibilityNodeInfo parent = node.getParent();
        while (parent != null) {
            if (parent.isClickable()) {
                parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                break;
            }
            parent = parent.getParent();
        }

    }

    /**
     * 递归查找当前聊天窗口中的红包信息
     *
     * 聊天窗口中的红包都存在"领取红包"一词,因此可根据该词查找红包
     *
     * @param node
     */
    public AccessibilityNodeInfo recycle(AccessibilityNodeInfo node) {
        int childCount = node.getChildCount();
        L.i(TAG, "childCount=" + childCount);
        if (childCount == 0) {
            CharSequence text = node.getText();
            if (text != null) {
                L.i(TAG, "text=" + text.toString());
                if ("微信红包".equals(text.toString())) {
                    return node;
                }
            }
        } else {
            for (int i = 0; i < childCount; i++) {
                AccessibilityNodeInfo child = node.getChild(i);
                if (child != null) {
                    recycle(child);
                }
            }
        }
        return node;
    }
}
